package com.maimao.goods.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baidu.fsg.uid.impl.CachedUidGenerator;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.maimao.core.constant.Constants;
import com.maimao.core.constant.ListData;
import com.maimao.core.constant.RedisKeys;
import com.maimao.core.enums.ExceptionEnum;
import com.maimao.core.enums.GoodsStatusEnum;
import com.maimao.core.exception.MaiMaoDaoException;
import com.maimao.core.exception.MaiMaoException;
import com.maimao.core.model.auth.AuthUser;
import com.maimao.core.model.resp.PageResult;
import com.maimao.core.model.resp.Result;
import com.maimao.core.utils.DateUtils;
import com.maimao.goods.client.*;
import com.maimao.goods.mapper.*;
import com.maimao.goods.utils.JvmCacheHolder;
import com.maimao.message.kafka.sender.KafkaSender;
import com.maimao.mg.service.MgCouponService;
import com.maimao.model.goods.*;
import com.maimao.model.goods.enums.GoodsCheckEnum;
import com.maimao.model.goods.input.GoodsSearch;
import com.maimao.model.goods.log.GoodsCheck;
import com.maimao.model.goods.vo.*;
import com.maimao.model.info.Collect;
import com.maimao.model.info.MgCoupon;
import com.maimao.model.info.vo.FollowGoods;
import com.maimao.model.kill.input.ActivityScheduleIdInput;
import com.maimao.model.kill.input.ApplySkuNewInput;
import com.maimao.model.user.Foot;
import com.maimao.model.user.Shop;
import com.maimao.model.user.input.SysUserByResourceInput;
import com.maimao.websocket.server.GoodsWebSocketServer;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.jni.Local;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.maimao.core.constant.Constants.GOODS_CHECK_RESOURCE_ID;
import static com.maimao.core.constant.Constants.ONE;

/**
 * @author MaoLin Wang
 * @date 2020/12/22 6:25 下午
 */
@Service
public class GoodsService {
    private Logger log = LoggerFactory.getLogger(GoodsService.class);


    @Autowired
    private ShopClient shopClient;

    @Autowired
    private BrandMapper brandMapper;

    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private UploadClient uploadClient;

    @Autowired
    private SpecDetailService specDetailService;

    @Autowired
    private GoodsDetailMapper goodsDetailMapper;
    @Autowired
    private GoodsSkuMapper goodsSkuMapper;

    @Autowired
    private SpecGroupMapper specGroupMapper;

    @Autowired
    private CateService cateService;

    @Autowired
    private KafkaSender kafkaSender;

    @Autowired
    private MgCouponService mgCouponService;

    @Autowired
    private CouponClient couponClient;

    @Autowired
    private SysUserClient sysUserClient;

    @Autowired
    private EsClient esClient;

    @Autowired
    private KillApplyClient killApplyClient;


    @Autowired
    private CachedUidGenerator cachedUidGenerator;

    @Autowired
    private RedisTemplate redisTemplate;

    public static final String MEMBER = "member";
    public static final String COMPANY = "company";


    /**
     * 商品发布
     *
     * @param goodsPublish
     * @param authUser
     */
    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void publish(GoodsPublish goodsPublish, AuthUser authUser) {
        Goods goods = goodsPublish.getGoods();
        goods.setClickCount(0L);
        goods.setCreateTime(DateUtils.now());
        goods.setDeleteTime(null);
        goods.setHot(0);
        goods.setRecommend(0);
        //需审核后通过
        goods.setStatus(GoodsStatusEnum.NOT_CHECK.getCode());
        goods.setSellCount(0);
        goods.setUpdateTime(DateUtils.now());
        Result<Shop> res = shopClient.findShopByOwner(Long.valueOf(authUser.getId()), authUser.getRole().equals(MEMBER) ? 0 : 1);
        Shop shop = res.getData();
        if (shop != null) {
            goods.setShopId(shop.getId());
        } else {
            throw new MaiMaoException(ExceptionEnum.NOT_APPLY_SHOP);
        }

        List<String> removeImages = goodsPublish.getRemoveImages();
        if (removeImages != null && removeImages.size() > 0) {
            //delete
            uploadClient.deleteBatch(removeImages);
        }

        List<SpecDetails> specDetailsList = specDetailService.getSpecDetailByCategoryId(goods.getCid3());

        List<GoodsSku> skus = goodsPublish.getSkus();
        BigDecimal minPrice = null;
        for (GoodsSku sku : skus) {
            fillSku(goods, specDetailsList, sku, true);
            if (minPrice == null) {
                minPrice = sku.getPrice();
            } else if (minPrice.compareTo(sku.getPrice()) > 0) {
                minPrice = sku.getPrice();
            }
        }
        if (minPrice == null) {
            minPrice = BigDecimal.valueOf(0);
        }
        goods.setMinPrice(minPrice);
        goodsMapper.insert(goods);

        GoodsDetail goodsDetail = goodsPublish.getGoodsDetail();
        goodsDetail.setGoodsId(goods.getId());

        goodsDetailMapper.insert(goodsDetail);

        for (GoodsSku sku : skus) {
            sku.setGoodsId(goods.getId());
            goodsSkuMapper.insert(sku);

        }

        sendWebSocket(goods);
        //TODO 管理员审核通过后再调用

    }


    /**
     * 修改宝贝
     */
    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public Result updateBaby(GoodsPublish goodsPublish, AuthUser authUser) {
        List<GoodsSku> skus = goodsPublish.getSkus();
        List<GoodsSku> updateSkus = Lists.newArrayListWithCapacity(skus.size());
        List<GoodsSku> insertSkus = Lists.newArrayListWithCapacity(skus.size());
        for (GoodsSku goodsSku : skus) {
            if (goodsSku.getId() == null) {
                insertSkus.add(goodsSku);
            } else {
                updateSkus.add(goodsSku);
            }
        }
        if (updateSkus.size() > 0) {
            Result result = checkSkuUpdate(updateSkus, goodsPublish.getGoods().getId());
            if (result != null) {
                return result;
            }
        }

        Goods goods = goodsPublish.getGoods();
        goods.setUpdateTime(DateUtils.now());


        GoodsDetail goodsDetail = goodsPublish.getGoodsDetail();
        goodsDetail.setGoodsId(goods.getId());

        goodsDetailMapper.updateById(goodsDetail);


        List<String> removeImages = goodsPublish.getRemoveImages();
        if (removeImages != null && removeImages.size() > 0) {
            //delete
            uploadClient.deleteBatch(removeImages);
        }

        List<SpecDetails> specDetailsList = specDetailService.getSpecDetailByCategoryId(goods.getCid3());

        BigDecimal minPrice = null;
        for (GoodsSku sku : insertSkus) {
            fillSku(goods, specDetailsList, sku, true);
            goodsSkuMapper.insert(sku);
            if (minPrice == null) {
                minPrice = sku.getPrice();
            } else if (minPrice.compareTo(sku.getPrice()) > 0) {
                minPrice = sku.getPrice();
            }
        }


        if (updateSkus.size() > 0) {
            for (GoodsSku sku : updateSkus) {
                fillSku(goods, specDetailsList, sku, false);
                if (minPrice == null) {
                    minPrice = sku.getPrice();
                } else if (minPrice.compareTo(sku.getPrice()) > 0) {
                    minPrice = sku.getPrice();
                }
            }
            goodsSkuMapper.updateBatch(updateSkus);
        }
        if (minPrice == null) {
            minPrice = BigDecimal.valueOf(0);
        }

        goods.setMinPrice(minPrice);
        goods.setStatus(GoodsStatusEnum.NOT_CHECK_UPDATE.getCode());
        goodsMapper.updateByGId(goods);
        sendWebSocket(goods);

//        kafkaSender.sendCallBack(publishTopic, String.valueOf(goods.getId()), String.valueOf(goods.getId()), new PublishCallback(publishTopic, goods.getId(), kafkaSender, esDocClient));

        return Result.ok();
    }

    public PageInfo<GoodsInfo> goodsInfoPage(Integer page, Integer size) {
        PageHelper.startPage(page, size);
        List<Goods> goodsList = goodsMapper.selectAll();
        PageInfo<Goods>goodsPageInfo=new PageInfo<>(goodsList);
        if (CollUtil.isNotEmpty(goodsList)) {
            List<GoodsInfo> goodsInfoList = new ArrayList<>(goodsList.size());
            GoodsInfo info = null;
            for (Goods goods : goodsList) {
                info = buildGoodsInfo(goods);
                goodsInfoList.add(info);
            }

            PageInfo<GoodsInfo> goodsInfoPageInfo = new PageInfo<>(goodsInfoList);
            goodsInfoPageInfo.setPages(goodsPageInfo.getPages());
            goodsInfoPageInfo.setIsLastPage(goodsPageInfo.isIsLastPage());
            goodsInfoPageInfo.setPageNum(goodsPageInfo.getPageNum());
            goodsInfoPageInfo.setPageSize(goodsPageInfo.getPageSize());
            return goodsInfoPageInfo;
        }
        return new PageInfo<>();
    }

    public GoodsInfo goodsInfoPageByGoodsId(Long goodsId) {
        Goods goods = goodsMapper.selectById(goodsId);
        if (goods != null) {
            GoodsInfo info = buildGoodsInfo(goods);
            return info;
        }
        return null;
    }


    /**
     * 商品详情页数据
     *
     * @param goodsId 商品id
     */
    public GoodsPage goodDetailPage(Long goodsId, Long userId) {
        GoodsPage goodsPage = new GoodsPage();
        Goods goods = goodsMapper.selectByIdValid(Long.valueOf(goodsId));
        if (goods == null) {
            return null;
        }
        //商品详情
        GoodsDetail goodsDetail = goodsDetailMapper.selectById(goodsId);
        List<SpecGroupEx> specGroupExes = specGroupMapper.selectExByCateId(goods.getCid3());
        List<GoodsSku> goodsSkus = goodsSkuMapper.selectByGoodsId(goodsId);
        List<Category> categories = cateService.selectBatch(Lists.newArrayList(goods.getCid1(), goods.getCid2(), goods.getCid3()));
        Brand brand = brandMapper.selectNameByIdSimple(goods.getBrandId());

        setSkuShowList(goodsPage, goodsDetail, specGroupExes);
        goodsPage.setGoods(goods);
        goodsPage.setGoodsDetail(goodsDetail);
        goodsPage.setSpecList(specGroupExes);
        goodsPage.setGoodsSkus(goodsSkus);
        goodsPage.setCategories(categories);
        goodsPage.setBrand(brand);

        //设置店铺信息
        setShop(goodsPage, goods);

        //设置优惠券信息
        setCoupons(goodsId, userId, goodsPage, goods);

        return goodsPage;
    }

    /**
     * 商品详情数据（后台审核商品查看商品信息，不包含优惠券、店铺等信息）
     */
    public GoodsPage goodsCheckDetail(Long goodsId) {
        GoodsPage goodsPage = new GoodsPage();
        Goods goods = goodsMapper.selectById(Long.valueOf(goodsId));
        if (ObjectUtil.isNull(goods)) {
            return goodsPage;
        }
        //商品详情
        GoodsDetail goodsDetail = goodsDetailMapper.selectById(goodsId);
        List<SpecGroupEx> specGroupExes = specGroupMapper.selectExByCateId(goods.getCid3());
        List<GoodsSku> goodsSkus = goodsSkuMapper.selectByGoodsId(goodsId);
        List<Category> categories = cateService.selectBatch(Lists.newArrayList(goods.getCid1(), goods.getCid2(), goods.getCid3()));
        Brand brand = brandMapper.selectNameByIdSimple(goods.getBrandId());

        setSkuShowList(goodsPage, goodsDetail, specGroupExes);
        goodsPage.setGoods(goods);
        goodsPage.setGoodsDetail(goodsDetail);
        goodsPage.setSpecList(specGroupExes);
        goodsPage.setGoodsSkus(goodsSkus);
        goodsPage.setCategories(categories);
        goodsPage.setBrand(brand);

        return goodsPage;
    }


    public List<GoodsSku> querySkusByIdBatch(List<Long> skuIds) {
        List<GoodsSku> goodsSkus = goodsSkuMapper.selectByIdsBatchValid(skuIds);
        return goodsSkus;
    }


    public PageResult<Goods> querySimpleByShop(Long shopId, String key, Integer page, Integer size, String userId) {
        if (shopId == null) {
            Result<Shop> res = shopClient.findShopByOwner(Long.valueOf(userId), 0);
            if (res == null || res.getData() == null) {
                return new PageResult<Goods>(ListData.EMPTY_LIST, 0L);
            }
            shopId = res.getData().getId();
        }
        PageHelper.startPage(page, size);
        List<Goods> goodsList = goodsMapper.selectIdNameByShopId(shopId, key);

        return new PageResult<>(goodsList);
    }

    public Boolean checkSku(Long skuId) {
        GoodsSku goodsSku = goodsSkuMapper.selectById(skuId);
        if (goodsSku == null) {
            return false;
        }
        if (goodsSku.getStock() <= 0 || !goodsSku.getValid().equals(1)) {
            return false;
        }

        Goods goods = goodsMapper.selectByIdValid(goodsSku.getGoodsId());
        return goods != null;
    }

    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void updateStock(Integer oper, Map<Long, Integer> stockMap) {
        if (oper.equals(1)) {
            //减库存
            for (Map.Entry<Long, Integer> entry : stockMap.entrySet()) {
                Long skuId = entry.getKey();
                Integer num = entry.getValue();
                int i = goodsSkuMapper.reduceStock(skuId, num);
                if (i <= 0) {
                    throw new MaiMaoDaoException(ExceptionEnum.STOCK_NOT_ENOUGH);
                }
            }
        } else {
            //加库存
            for (Map.Entry<Long, Integer> entry : stockMap.entrySet()) {
                Long skuId = entry.getKey();
                Integer num = entry.getValue();
                goodsSkuMapper.addStock(skuId, num);
            }
        }

    }

    /**
     * 查询店铺商品
     *
     * @param shopId 店铺id
     * @return PageResult<GoodsVo>
     */
    public PageResult<GoodsVo> shopGoodsList(Long shopId, GoodsSearch goodsSearch, Integer page, Integer size) {
        PageHelper.startPage(page, size);
        List<Goods> goods = goodsMapper.selectByShopId(shopId, goodsSearch);
        if (ObjectUtils.isNotEmpty(goods)) {
            PageInfo<Goods> pageInfo = new PageInfo<>(goods);
            List<GoodsVo> voList = Lists.newArrayListWithCapacity(goods.size());
            GoodsVo vo = null;
            List<Goods> goodsList = pageInfo.getList();
            //当前店铺商品的所有三级分类
            long total = pageInfo.getTotal();
            Set<Integer> cid3s = goodsList.stream().map(Goods::getCid3).collect(Collectors.toSet());
            for (Goods good : goodsList) {
                vo = new GoodsVo();
                List<GoodsSku> goodsSkus = goodsSkuMapper.selectByGoodsId(good.getId());
                goodsSkus = filterPriceAndSellCount(goodsSearch.getPriceMin(), goodsSearch.getPriceMax(), goodsSkus, getSpecDetailsMap(cid3s));
               /* if (goodsSkus.size() <= 0) {
                    //TODO 不能这么写 分页出错
                    total -= 1;
                    continue;
                }*/
                if (goodsSearch.getActivityId() != null && goodsSearch.getScheduleId() != null) {
                    goodsSkus = filterKillApplied(goodsSkus, goodsSearch.getActivityId(), goodsSearch.getScheduleId());
                }
                vo.setGoodsSkuList(goodsSkus);
                BeanUtils.copyProperties(good, vo);
                Brand brand = brandMapper.selectIdLogoNameById(good.getBrandId());
                vo.setBrand(brand);
                List<Category> categories = cateService.selectBatch(Lists.newArrayList(good.getCid1(), good.getCid2(), good.getCid3()));
                if (ObjectUtils.isNotEmpty(categories)) {
                    StringBuilder sb = new StringBuilder();
                    for (Category category : categories) {
                        sb.append(category.getName()).append(Constants.MIDDLE_LINE_STR);
                    }
                    String categoryName = sb.toString();
                    vo.setCategory(categoryName.substring(0, categoryName.length() - 1));
                }
                voList.add(vo);
            }
            return new PageResult<>(voList, total);
        }
        return new PageResult<>(ListData.EMPTY_LIST, 0L);
    }

    /**
     * 过滤掉当前商户当前活动当前排期已经报名或申请的sku
     *
     * @param goodsSkus  待过滤的sku列表
     * @param activityId 活动id
     * @param scheduleId 排期id
     * @return 过滤后的sku列表
     */
    private List<GoodsSku> filterKillApplied(List<GoodsSku> goodsSkus, Integer activityId, Long scheduleId) {
        Result<List<Long>> res = killApplyClient.querySkuIdsByAcSch(new ActivityScheduleIdInput(activityId, scheduleId));
        if (res == null || res.getData() == null) {
            return goodsSkus;
        }
        List<Long> appliedSkuIds = res.getData();
        return goodsSkus.stream().filter(sku -> !appliedSkuIds.contains(sku.getId())).collect(Collectors.toList());
    }

    /**
     * 增加销量
     *
     * @param sellCountMap
     */
    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void addSellCount(Map<Long, Integer> sellCountMap) {
        for (Map.Entry<Long, Integer> entry : sellCountMap.entrySet()) {
            goodsMapper.addSellcount(entry.getKey(), entry.getValue());
        }
    }


    /**
     * 校验商品是否有效 一个不有效即返回false
     *
     * @param goodsIdList
     * @return
     */
    public boolean checkSpuBatch(List<Long> goodsIdList) {
        List<Goods> goods = goodsMapper.selecBatchtByIdValid(goodsIdList);
        if (goods == null || goods.size() <= 0 || goods.size() != goodsIdList.size()) {
            return false;
        }
        return true;
    }

    /**
     * 校验商品是否有效 返回无效的goodsId
     *
     * @param goodsIdList 商品ID
     * @return
     */
    public List<Long> checkSpuBatchWithInvalid(List<Long> goodsIdList) {
        List<Goods> goods = goodsMapper.selecBatchtByIdValid(goodsIdList);
        if (ObjectUtil.isEmpty(goods)) {
            return goodsIdList;
        }
        if (goods.size() != goodsIdList.size()) {
            List<Long> validIds = goods.stream().map(Goods::getId).collect(Collectors.toList());
            goodsIdList.removeAll(validIds);
            return goodsIdList;
        }
        return ListData.EMPTY_LIST;
    }

    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void updateSellStatus(Long goodsId, Integer onSell) {
        goodsMapper.updateOnSell(goodsId, onSell, onSell.equals(1) ? null : DateUtils.now());

    }

    public List<Foot> userFoot(List<Long> goodsIdList) {
        List<Goods> goods = goodsMapper.selectByIdBatch(goodsIdList);
        if (goods != null && goods.size() > 0) {
            List<Foot> footList = Lists.newArrayListWithCapacity(goods.size());
            Foot foot = null;
            //mysql查询后，顺序和goodsIdList不一样了，这里暂时按goodsIdList顺序封装结果
            Map<Long, Goods> goodsMap = Maps.newHashMapWithExpectedSize(goodsIdList.size());
            for (Goods good : goods) {
                goodsMap.put(good.getId(), good);
            }
            for (Long id : goodsIdList) {
                Goods target = goodsMap.get(id);
                if (target == null) {
                    foot = new Foot();
                    foot.setGoodsId(id.toString());
                    foot.setPrice(BigDecimal.valueOf(0));
                    foot.setTitle("失效宝贝");
                    foot.setValid(false);
                    footList.add(foot);
                } else {
                    List<GoodsSku> goodsSkus = goodsSkuMapper.selectByGoodsId(target.getId());
                    foot = new Foot();
                    foot.setGoodsId(target.getId().toString());
                    foot.setPrice(target.getMinPrice());
                    if (ObjectUtils.isNotEmpty(goodsSkus)) {
                        String pictures = goodsSkus.get(0).getPictures();
                        if (!StringUtils.isEmpty(pictures)) {
                            List<String> pictureList = JSON.parseObject(pictures, List.class);
                            if (ObjectUtils.isNotEmpty(pictureList)) {
                                foot.setPicture(pictureList.get(0));
                            }
                        }
                    }
                    foot.setValid(target.getOnSell() != null && target.getOnSell().equals(1) ? true : false);
                    foot.setTitle(target.getName());
                    footList.add(foot);
                }
            }

            return footList;
        }
        return ListData.EMPTY_LIST;
    }

    /**
     * 用户关注商品列表
     *
     * @param collectList
     * @return
     */
    public List<FollowGoods> followGoods(List<Collect> collectList) {
        List<Long> goodsIdList = collectList.stream().map(Collect::getTargetId).collect(Collectors.toList());
        List<Goods> goods = goodsMapper.selectByIdBatch(goodsIdList);
        if (goods != null && goods.size() > 0) {
            List<FollowGoods> followGoodsList = Lists.newArrayListWithCapacity(goods.size());
            FollowGoods foot = null;
            Map<Long, Goods> goodsMap = goods.stream().collect(Collectors.toMap(Goods::getId, c -> c));
            for (Collect collect : collectList) {
                foot = new FollowGoods();
                Goods good = goodsMap.get(collect.getTargetId());
                if (null != good) {
                    BeanUtils.copyProperties(collect, foot);
                    List<GoodsSku> goodsSkus = goodsSkuMapper.selectByGoodsId(good.getId());
                    foot.setPrice(good.getMinPrice());
                    if (ObjectUtils.isNotEmpty(goodsSkus)) {
                        String pictures = goodsSkus.get(0).getPictures();
                        if (!StringUtils.isEmpty(pictures)) {
                            List<String> pictureList = JSON.parseObject(pictures, List.class);
                            if (ObjectUtils.isNotEmpty(pictureList)) {
                                foot.setPicture(pictureList.get(0));
                            }
                        }
                    }
                    foot.setValid(good.getOnSell() != null && good.getOnSell().equals(1) ? true : false);
                    foot.setTitle(good.getName());
                    followGoodsList.add(foot);
                }
            }
            return followGoodsList;
        }
        return ListData.EMPTY_LIST;
    }

    /**
     * 设置商品优惠券信息
     *
     * @param goodsId 商品id
     * @param userId  用户id
     * @param goods   商品实体
     */
    private void setCoupons(Long goodsId, Long userId, GoodsPage goodsPage, Goods goods) {
        List<MgCoupon> mgCoupons = mgCouponService.selectGoodsCoupon(goods.getShopId(), goodsId);
        if (userId != null && mgCoupons != null && mgCoupons.size() > 0) {
            List<Long> couponIds = mgCoupons.stream().map(MgCoupon::getId).collect(Collectors.toList());
            Result<Map<Long, Boolean>> res = couponClient.couponUserExist(couponIds, userId);
            if (res != null && res.getData() != null) {
                Map<Long, Boolean> couponUserExitMap = res.getData();
                for (MgCoupon mgCoupon : mgCoupons) {
                    Boolean taked = couponUserExitMap.get(mgCoupon.getId());
                    mgCoupon.setCan(taked == null ? true : !taked);
                }
            }
        }
        goodsPage.setMgCoupons(mgCoupons);
    }

    /**
     * 设置店铺信息
     */
    private void setShop(GoodsPage goodsPage, Goods goods) {
        Result<Shop> shopResult = shopClient.queryByIdIn(goods.getShopId());
        if (shopResult != null && shopResult.getData() != null) {
            goodsPage.setShop(shopResult.getData());
        }
    }

    /**
     * 设置详情页销售规格
     *
     * @param goodsPage     详情页引用
     * @param goodsDetail   商品详情
     * @param specGroupExes 规格组
     */
    private void setSkuShowList(GoodsPage goodsPage, GoodsDetail goodsDetail, List<SpecGroupEx> specGroupExes) {
        //key:规格id value：对应的specDetails 集合只有一个元素
        Map<Integer, SpecDetails> specDetailsMap = specGroupExes.stream().flatMap(item -> item.getSpecDetailsList().stream()).collect(Collectors.toMap(SpecDetails::getId, c -> c));

        // key:规格id value：规格值列表
        LinkedHashMap<String, Object> skuParamMap = JSON.parseObject(goodsDetail.getSkuParam(), LinkedHashMap.class);
        if (skuParamMap != null && skuParamMap.size() > 0) {
            List<SkuShow> skuShowList = new ArrayList<>(skuParamMap.size());
            SkuShow skuShow;
            for (Map.Entry<String, Object> skuParam : skuParamMap.entrySet()) {
                skuShow = new SkuShow();
                skuShow.setId(Integer.valueOf(skuParam.getKey()));
                skuShow.setValues((List<Object>) skuParam.getValue());
                SpecDetails specDetails = specDetailsMap.get(skuShow.getId());
                if (specDetails != null) {
                    skuShow.setName(specDetails.getName());
                    skuShow.setGroupId(specDetails.getGroupId());
                    skuShow.setUnit(specDetails.getUnit());
                }
                skuShowList.add(skuShow);
            }
            goodsPage.setSkuShowList(skuShowList);
        }
    }


    /**
     * 获取规格map key：规格id value：规格项 （只有一个元素）
     *
     * @param cid3s 所有三级分类
     * @return
     */
    private Map<String, List<SpecDetails>> getSpecDetailsMap(Set<Integer> cid3s) {
        Set<SpecDetails> specDetailsSet = Sets.newHashSet();
        for (Integer cid3 : cid3s) {
            List<SpecDetails> specDetailsList = specDetailService.getSpecDetailByCategoryId(cid3);
            specDetailsSet.addAll(specDetailsList);
        }

        return specDetailsSet.stream().collect(Collectors.groupingBy(specDetails -> specDetails.getId().toString()));
    }

    /**
     * 按价格过滤 并重新封装sku的图片和规格 会影响分页结果 为了方便没有连表查询过滤
     */
    private List<GoodsSku> filterPriceAndSellCount(BigDecimal priceMin, BigDecimal priceMax, List<GoodsSku> goodsSkus, Map<String, List<SpecDetails>> specDetailMap) {
        if (ObjectUtils.isNotEmpty(goodsSkus)) {

            return goodsSkus.stream().filter(sku -> {

                //过滤价格
                if (priceMin != null && priceMin.compareTo(BigDecimal.ZERO) >= 0) {
                    if (sku.getPrice().compareTo(priceMin) < 0) {
                        return false;
                    }
                }
                if (priceMax != null && priceMax.compareTo(BigDecimal.ZERO) >= 0) {
                    if (sku.getPrice().compareTo(priceMax) > 0) {
                        return false;
                    }
                }
                //设置展示图片
                Integer showIndex = sku.getShowIndex();
                String pictures = sku.getPictures();
                List<String> pictureList = JSON.parseObject(pictures, List.class);
                sku.setPictures(pictureList.size() > 0 ? pictureList.get((showIndex == null || showIndex < 0) ? 0 : showIndex) : "");

                //设置规格
                String spec = sku.getSpec();
                //key：规格id value：规格值
                Map<String, Object> specMap = JSON.parseObject(spec, Map.class);
                StringBuilder sb = new StringBuilder();
                if (specMap.size() > 0) {
                    for (Map.Entry<String, Object> specEntry : specMap.entrySet()) {
                        List<SpecDetails> specDetailsList = specDetailMap.get(specEntry.getKey());
                        if (specDetailsList != null && specDetailsList.size() == 1) {
                            SpecDetails specDetails = specDetailsList.get(0);
                            sb.append(specDetails.getName()).append(Constants.CH_MAOHAO).append(specEntry.getValue());
                            if (!StringUtils.isEmpty(specDetails.getUnit())) {
                                sb.append(specDetails.getUnit());
                            }
                            sb.append(Constants.NEW_LINE);
                        }
                    }
                }
                sku.setSpec(sb.toString());

                return true;
            }).collect(Collectors.toList());
        } else {
            return goodsSkus;
        }
    }

    private GoodsInfo buildGoodsInfo(Goods goods) {
        GoodsInfo info = new GoodsInfo();
        Result<Shop> shopResult = shopClient.queryByIdIn(goods.getShopId());
        if (shopResult != null && shopResult.getData() != null) {
            Shop shop = shopResult.getData();
            goods.setShopName(shop.getName());
        }
        GoodsDetail goodsDetail = goodsDetailMapper.selectById(goods.getId());
        List<GoodsSku> goodsSkus = goodsSkuMapper.selectByGoodsId(goods.getId());

        info.setGoods(goods);
        info.setGoodsDetail(goodsDetail);
        info.setSkus(goodsSkus);
        return info;
    }

    /**
     * 封装sku（商品发布和修改）
     *
     * @param goods
     * @param specDetailsList
     * @param sku
     */
    private void fillSku(Goods goods, List<SpecDetails> specDetailsList, GoodsSku sku, boolean publish) {
        sku.setGoodsId(goods.getId());
        Map<String, Object> specMap = JSON.parseObject(sku.getSpec(), Map.class);
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, Object> entry : specMap.entrySet()) {
            Optional<SpecDetails> spec = specDetailsList.stream().filter(s -> (s.getId() + "").equals(entry.getKey())).findFirst();
            if (spec.isPresent()) {
                SpecDetails specDetails = spec.get();
                if (!StringUtils.isEmpty(specDetails.getUnit())) {
                    //添加单位
                    sb.append(entry.getValue()).append(specDetails.getUnit()).append(Constants.BLANK);
                    continue;
                }
            }
            sb.append(entry.getValue()).append(Constants.BLANK);
        }

        sku.setName(goods.getName() + Constants.BLANK + sb.toString());
        sku.setPictures(JSON.toJSONString(sku.getPictureList()));
        sku.setValid(1);
        sku.setSecKill(0);
        sku.setIntegral((sku.getIntegral() != null && sku.getIntegral() > 0) ? (sku.getPrice().intValue() / 100) : 0);
        sku.setGiveIntegral((sku.getIntegral() != null && sku.getIntegral() > 0) ? true : false);

        if (publish) {
            sku.setCreateTime(DateUtils.now());
        }
        sku.setUpdateTime(DateUtils.now());
        sku.setPrice(sku.getPrice().setScale(2, RoundingMode.HALF_UP));
    }


    /**
     * 检查sku 1.不允许添加/删除已有销售属性 2.不允许删除已有sku规格项 3.已有SKU规格的库存只允许增加不允许减少
     *
     * @param skus
     * @param goodsId 商品id
     */
    private Result checkSkuUpdate(List<GoodsSku> skus, Long goodsId) {
        //原始sku
        List<GoodsSku> rawGoodsSkus = goodsSkuMapper.selectByGoodsId(goodsId);
        Map<Long, GoodsSku> skuMap = Maps.newHashMapWithExpectedSize(skus.size());
        for (GoodsSku goodsSku : skus) {
            skuMap.put(goodsSku.getId(), goodsSku);
        }
        if (ObjectUtils.isNotEmpty(rawGoodsSkus)) {
            if (rawGoodsSkus.size() != skus.size()) {
                return Result.notValid("已发布的商品禁止移除已发布规格项，只能修改价格和库存，可在商品中心清空库存；如要更改SKU详细信息，则需要先下架该商品，重新上架相关的商品");
            }
            for (GoodsSku goodsSku : rawGoodsSkus) {
                GoodsSku target = skuMap.get(goodsSku.getId());
                if (target == null) {
                    return Result.notValid("已发布的商品禁止移除已发布规格项，只能修改价格和库存，可在商品中心清空库存；如要更改SKU详细信息，则需要先下架该商品，重新上架相关的商品");
                }
                if (target.getStock() < goodsSku.getStock()) {
                    return Result.notValid("原始规格项的库存只能增加不能减少");
                }
            }
        }
        return null;
    }


    /**
     * 商品发布/修改后 发送websocket ，要求管理员审核信息
     */
    private void sendWebSocket(Goods goods) {
        String clientId = null;
        try {
            clientId = GoodsWebSocketServer.sendInfo(String.valueOf(goods.getId()));
            if (StringUtils.isEmpty(clientId)) {
                //暂时没有上线的管理员，从库中查询
                Result<Set<Integer>> sysUserRes = sysUserClient.queryByResource(
                        SysUserByResourceInput.builder()
                                .limit(ONE)
                                .resourcesIds(ListUtil.toList(GOODS_CHECK_RESOURCE_ID))
                                .build()
                );
                if (sysUserRes.getData() != null) {
                    Set<Integer> sysUserIds = sysUserRes.getData();
                    if (CollUtil.isNotEmpty(sysUserIds)) {
                        clientId = sysUserIds.toArray()[0].toString();
                    }
                }

            }
            this.saveToEs(goods, clientId);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("websocket send message to client: {} error ", clientId == null ? "尚未客户端连接" : clientId);
        }
    }

    /**
     * 保存审核记录到ES
     *
     * @param goods    商品
     * @param clientId 审核人id
     */
    private void saveToEs(Goods goods, String clientId) {
        Brand brand = JvmCacheHolder.brandCache.get(goods.getBrandId());
        esClient.save(GoodsCheck.builder().deliveryTime(DateUtils.now())
                .goodsId(String.valueOf(goods.getId()))
                .sysUserId(clientId)
                .brandId(String.valueOf(goods.getBrandId()))
                .brandName(brand == null ? Constants.EMPTY : brand.getName())
                .logo(brand == null ? Constants.EMPTY : brand.getLogo())
                .goodsName(goods.getName())
                .id(String.valueOf(cachedUidGenerator.getUID()))
                .status(GoodsCheckEnum.WAITING.getCode())
                .build());

    }


    /**
     * 统计商品各个数量
     *
     * @return
     */
    public GoodsCountVo msGoodsOverView() {
        GoodsCountVo vo = new GoodsCountVo();
        Integer totalCount = goodsMapper.total(null);
        Long totalSellCount = goodsMapper.totalSellCount();
        Long totalClickCount = goodsMapper.selectTotalClickCount();
        Integer newCount = goodsMapper.total(DateUtils.now().plusDays(-6));
        Integer skuCount = goodsSkuMapper.total();

        vo.setGoodsCount(totalCount);
        vo.setNewGoodsCount(newCount);
        vo.setTotalClickCount(totalClickCount);
        vo.setSkuCount(skuCount);
        vo.setTotalSellCount(totalSellCount);

        String todayClickRedisKey = getTodayClickRedisKey();
        //redis中没有long类型，要手动转换下，不可强转，否则CCE
        List<Integer> values = redisTemplate.opsForHash().values(todayClickRedisKey);
        if (ObjectUtil.isNotEmpty(values)) {
            long sum = values.stream().mapToLong(cnt -> Long.parseLong(cnt.toString())).sum();
            vo.setCurrentDayClickCount(sum);
        } else {
            vo.setCurrentDayClickCount(0L);
        }
        return vo;

    }


    /**
     * 增加商品点击
     *
     * @param goodsId
     */
    public void addClick(String goodsId) {
        redisTemplate.opsForHash().increment(getTodayClickRedisKey(), goodsId, 1L);
    }

    public String getTodayClickRedisKey() {
        String format = DateUtils.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return String.format(RedisKeys.GOODS_CLICK_COUNT, format);
    }

    public ApplySkuNewInput checkSkuNew(List<Long> skuIds, LocalDateTime fromTime) {
        List<GoodsSku> goodsSkus = goodsSkuMapper.selectByIdsBatchValid2(skuIds);
        ApplySkuNewInput input = new ApplySkuNewInput();
        if (ObjectUtil.isEmpty(goodsSkus) || goodsSkus.size() != skuIds.size()) {
            List<Long> existIds = goodsSkus.stream().map(GoodsSku::getId).collect(Collectors.toList());
            skuIds.removeAll(existIds);
            input.setNotValidIds(skuIds);
        }
        //新上架的skuId
        List<Long> newIds = goodsSkus.stream().filter(sku -> sku.getCreateTime().compareTo(fromTime) >= 0).map(GoodsSku::getId).collect(Collectors.toList());
        input.setSkuIds(newIds);
        return input;
    }

    public static void main(String[] args) {

    }

    public Long queryBrandIdByGoodsId(Long goodsId) {
        return goodsMapper.selectBrandIdById(goodsId);
    }
}
